/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package fr.vod.gauss.File;

import fr.vod.gauss.encoder.Encoder;
import fr.vod.gauss.utils.Convert;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.Arrays;

/**
 *
 * @author drazanakoto
 */
public class FileImpl implements File {

    private int blockSize;
    private int packetSize;
    private InputStream fis;
    private Encoder encoder;
    private byte[] dataRead;
    private long blockNumber = -1;
    private int compteur;
    private int initCreate = 0;
    private int bPivotGauss = 0; 


    /**
     *
     * @param fis
     * @param encoder
     * @param blockSize
     * @param packetSize
     */
    public FileImpl(InputStream fis, Encoder encoder, int blockSize, int packetSize,int bPivotGauss) {
        this.blockSize = blockSize;
        this.packetSize = packetSize;
        this.fis = fis;
        this.encoder = encoder;
        this.dataRead = new byte[blockSize];
        this.bPivotGauss = bPivotGauss;
        compteur = 0;
    }

    /**
     *
     *
     * @param encoder
     * @return
     */
    @Override
    public byte[] create() {
        /*if (initCreate < blockSize) {
            initCreate += packetSize;
            return normal();
        }*/
        return normal();
    }

    /**
     *
     * @return @throws Exception
     */
    @Override
    public int readNextBlock() throws Exception {
        blockNumber++;
        compteur = 0;
        initCreate = 0;
        return fis.read(dataRead);
    }
    
    /**
    *
    * @return @throws Exception
    */
   @Override
   public int readBlock(long blockNumber) throws Exception {
       this.blockNumber = blockNumber;
       compteur = 0;
       initCreate = 0;
       return fis.read(dataRead, (int)blockNumber * blockSize, dataRead.length);
   }

    /**
     *
     * @return
     */
    @Override
    public int getBlockSize() {
        return blockSize;
    }

    /**
     *
     * @param blockSize
     */
    @Override
    public void setBlockSize(int blockSize) {
        this.blockSize = blockSize;
    }

    /**
     *
     * @return
     */
    @Override
    public int getPacketSize() {
        return packetSize;
    }

    /**
     *
     * @param packetSize
     */
    @Override
    public void setPacketSize(int packetSize) {
        this.packetSize = packetSize;
    }

    /**
     *
     * @param data
     * @param indices
     * @return
     */
    protected int[] getData(byte[] data, int[] indices) {
        int[] result = new int[indices.length];
        byte tmp;
        for (int i = 0; i < indices.length; i++) {
            /**
             * get data correspond to indice *
             */
            tmp = data[indices[i]];
            /**
             * convert data to int *
             */
            result[i] = Convert.byteToUint8(tmp);
        }
        return result;
    }

    /**
     *
     * @param data
     * @return
     */
    protected byte[] intArrayToByteArray(int[] data) {
        byte[] block = ByteBuffer.allocate(SIZE_OF_BLOCK_NUMBER).putLong(blockNumber).array();
        byte[] result = new byte[data.length + SIZE_OF_BLOCK_NUMBER + 1];

        /**
         * encodage des blocks
         */
        result[0] = 1;

        /**
         * *
         */
        System.arraycopy(block, 0, result, 1, SIZE_OF_BLOCK_NUMBER);

        /**
         * *
         */
        for (int i = 0; i < data.length; i++) {
            result[SIZE_OF_BLOCK_NUMBER + 1 + i] = Convert.uint8ToByte(data[i]);
        }
        return result;
    }

    /**
     *
     * @return
     */
    @Override
    public long getBlockNumber() {
        return blockNumber;
    }

    /**
     *
     * @return
     */
    protected byte[] xor() {
        int[] result = new int[2 * bPivotGauss + 1];
        int[] dataChoose;
        int[] symboles = encoder.generateSymboles(bPivotGauss);
        int[] indiceData = encoder.generateDataIndice(bPivotGauss, bPivotGauss);

        /**
         *
         */
        System.arraycopy(indiceData, 0, result, 0, bPivotGauss);

        System.arraycopy(symboles, 0, result, bPivotGauss, bPivotGauss);

        /**
         * get data corresponds to generate indice
         */
        dataChoose = getData(dataRead, indiceData);

        /**
         * calcul check Sum *
         */
        result[result.length - 1] = encoder.calculCheckSum(dataChoose, symboles);

        /**
         * convert int array result to byte array *
         *
         */
        return intArrayToByteArray(result);
    }

    /**
     *
     * @return
     */
    protected byte[] normal() {
        byte[] block = ByteBuffer.allocate(SIZE_OF_BLOCK_NUMBER).putLong(blockNumber).array();
        byte[] result = new byte[1 + SIZE_OF_BLOCK_NUMBER + blockSize];

        /**
         * sans encodage des packets
         */
        result[0] = 0;

        /**
         * *
         */
        System.arraycopy(block, 0, result, 1, SIZE_OF_BLOCK_NUMBER);
        
        /**
         * 
         */
        System.arraycopy(dataRead, 0, result, 1 + SIZE_OF_BLOCK_NUMBER, blockSize);
        return result;
    }

    public String toString() {
        return "Block n° " + blockNumber + "\nContenu " + Arrays.toString(dataRead);
    }
}
